package com.my.kindlesend.controller;

import cn.hutool.core.io.FileUtil;
import com.my.kindlesend.dto.FileUploadRequestDto;
import com.my.kindlesend.entity.FileInfo;
import com.my.kindlesend.entity.UploadFile;
import com.my.kindlesend.entity.UserInfo;
import com.my.kindlesend.result.Result;
import com.my.kindlesend.service.FileUploadService;
import com.my.kindlesend.service.UploadFileService;
import com.my.kindlesend.utils.UserThreadLocal;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;

import javax.validation.Valid;

/**
 * 微信文件控制器
 * 处理微信端的文件上传请求
 */
@Slf4j
@RestController
@RequestMapping("/wx")
@RequiredArgsConstructor
public class WxFileController {

    @Value("${file.upload.path}")
    private String uploadPath;
    
    @Value("${file.upload.url-prefix}")
    private String urlPrefix;

    private final FileUploadService fileUploadService;
    private final UploadFileService uploadFileService;
    
    /**
     * 查询用户的上传文件列表
     * @return 用户的上传文件列表
     */
    @GetMapping("/files")
    public Result<List<UploadFile>> getUploadFiles() {
        // 获取当前登录用户
        UserInfo currentUser = UserThreadLocal.get();
        if (currentUser == null) {
            log.warn("用户未登录尝试查询文件列表");
            return Result.error("用户未登录");
        }
        
        try {
            // 根据用户的openId查询上传文件列表
            List<UploadFile> uploadFiles = uploadFileService.getUploadFilesByOpenId(currentUser.getOpenId());
            log.info("用户[{}]查询文件列表，共{}个文件", currentUser.getId(), uploadFiles.size());
            return Result.success(uploadFiles);
        } catch (Exception e) {
            log.error("查询文件列表失败：{}", e.getMessage(), e);
            return Result.error("查询文件列表失败：" + e.getMessage());
        }
    }
    
    /**
     * 文件上传接口
     * 处理用户上传的文件，生成唯一文件名，保存文件，并记录文件信息
     * @param requestDto 文件上传请求DTO
     * @return 上传结果，包含文件ID和相关信息
     */
    @PostMapping("/upload")
    public Result<?> uploadFile(@Valid @ModelAttribute FileUploadRequestDto requestDto) {
        MultipartFile file = requestDto.getFile();
        
        // 获取当前登录用户
        UserInfo currentUser = UserThreadLocal.get();
        if (currentUser == null) {
            log.warn("用户未登录尝试上传文件");
            return Result.error("用户未登录");
        }
        
        try {
            // 确保上传目录存在
            File dir = new File(uploadPath);
            if (!dir.exists() && !dir.mkdirs()) {
                throw new RuntimeException("创建上传目录失败");
            }
            
            // 生成唯一文件名
            String originalFilename = file.getOriginalFilename();
            String fileExtension = FileUtil.getSuffix(originalFilename);
            String fileName = UUID.randomUUID() + "." + fileExtension;
            String filePath = uploadPath + fileName;
            String fileUrl = urlPrefix + fileName;
            
            // 保存文件
            file.transferTo(new File(filePath));
            log.debug("文件保存成功，路径：{}", filePath);
            
            // 创建并保存文件信息
            FileInfo fileInfo = buildFileInfo(originalFilename, fileName, filePath, fileUrl, file);
            UploadFile uploadFile = fileUploadService.uploadFile(fileInfo, currentUser.getId());
            
            log.info("用户[{}]文件上传成功，文件ID：{}", currentUser.getId(), uploadFile.getId());
            return Result.success("文件上传成功", uploadFile);
        } catch (IOException e) {
            log.error("文件上传失败：{}", e.getMessage(), e);
            return Result.error("文件上传失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("系统异常：{}", e.getMessage(), e);
            return Result.error("系统异常：" + e.getMessage());
        }
    }
    
    /**
     * 将文件发送状态重置为未发送
     * @param fileId 要重置状态的文件ID
     * @return 重置结果
     */
    @PostMapping("/files/reset/{fileId}")
    public Result<?> resetFileStatus(@PathVariable Long fileId) {
        // 获取当前登录用户
        UserInfo currentUser = UserThreadLocal.get();
        if (currentUser == null) {
            log.warn("用户未登录尝试重置文件状态");
            return Result.error("用户未登录");
        }
        
        try {
            // 调用服务层方法重置文件状态
            boolean success = uploadFileService.resetFileStatusToNotSent(fileId, currentUser.getOpenId());
            if (success) {
                log.info("用户[{}]重置文件[{}]状态成功", currentUser.getId(), fileId);
                return Result.success("文件状态已成功重置为未发送");
            } else {
                log.warn("用户[{}]重置文件[{}]状态失败", currentUser.getId(), fileId);
                return Result.error("文件状态重置失败，请检查文件是否存在或是否属于您");
            }
        } catch (Exception e) {
            log.error("重置文件状态失败：{}", e.getMessage(), e);
            return Result.error("重置文件状态失败：" + e.getMessage());
        }
    }
    
    /**
     * 构建FileInfo对象
     * 根据上传文件的信息创建文件信息对象
     * @param originalFilename 原始文件名
     * @param filePath 文件保存路径
     * @param fileUrl 文件访问URL
     * @param file 上传的文件对象
     * @return 构建好的FileInfo对象
     */
    private FileInfo buildFileInfo(String originalFilename, String fileName, String filePath, String fileUrl, MultipartFile file) {
        FileInfo fileInfo = new FileInfo();
        fileInfo.setOriginalFilename(originalFilename);
        fileInfo.setFileName(fileName);
        fileInfo.setFilePath(filePath);
        fileInfo.setFileUrl(fileUrl);
        fileInfo.setFileSize(String.valueOf(file.getSize()));
        fileInfo.setFileType(file.getContentType());
        return fileInfo;
    }
}